package org.netty.framework.tcpserver.handle;

import java.lang.reflect.Method;
import java.net.SocketAddress;

import org.netty.framework.core.annotation.HandlerExecutionChain;
import org.netty.framework.core.codec.CustomMsg;
import org.netty.framework.core.codec.Header;
import org.netty.framework.core.concurrent.NettyServerThreadPoolExecutor;
import org.netty.framework.core.concurrent.TcpServerThreadPoolExecutor;
import org.netty.framework.core.util.AnnotationContainer;
import org.netty.framework.tcpserver.tcp.TcpServerRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 处理客户端请求,分发请求
 * 
 * @author chenfanglin
 * @date 2018年9月29日下午4:39:59
 *
 */
public class TcpChannelHandle extends SimpleChannelInboundHandler<CustomMsg<?>> {

	private static final Logger logger = LoggerFactory.getLogger(TcpChannelHandle.class);

	private NettyServerThreadPoolExecutor nettyServerThreadPoolExecutor;

	public TcpChannelHandle() {
		nettyServerThreadPoolExecutor = TcpServerThreadPoolExecutor.getInstance().getThreadPoolExecutor();
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		SocketAddress socketAddress = ctx.channel().remoteAddress();
		logger.info("远程主机连接成功,远程主机:{}", socketAddress);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		logger.info("Channel发生异常:{}", cause);
		ctx.close();
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, CustomMsg<?> msg) throws Exception {
		TcpServerRequest<CustomMsg<?>> request = new TcpServerRequest<CustomMsg<?>>(msg);
		nettyServerThreadPoolExecutor.execute(new TcpRequestTask(ctx, request));
	}

	/**
	 * 执行tcp请求的业务线程
	 */
	private class TcpRequestTask implements Runnable {
		private ChannelHandlerContext ctx;
		private TcpServerRequest<CustomMsg<?>> request;

		public TcpRequestTask(ChannelHandlerContext ctx, TcpServerRequest<CustomMsg<?>> request) {
			this.ctx = ctx;
			this.request = request;
		}

		@Override
		public void run() {
			try {
				dispatch(ctx, request);
			} catch (Exception e) {
				logger.error("处理tcp请求失败:{}", e);
			}
		}
	}

	/**
	 * 根据cmd请求到对应的Process上
	 * 
	 * @param ctx
	 * @param request
	 */
	private void dispatch(ChannelHandlerContext ctx, TcpServerRequest<CustomMsg<?>> request) {
		Object result = null;
		try {
			Header header = request.getMsg().getHeader();
			if (header != null) {
				long cmd = header.getCmd();
				HandlerExecutionChain process = AnnotationContainer.getProcess(cmd);
				Method method = process.getMethod();
				result = method.invoke(process.getHandle(), request);
			}
		} catch (Exception e) {
			result = "无效的cmd";
		} finally {
			writeResponse(ctx, result);
		}
	}

	/**
	 * 将结果写入channel
	 * 
	 * @param ctx
	 * @param result
	 */
	private void writeResponse(ChannelHandlerContext ctx, Object result) {
		ctx.writeAndFlush(result);
	}
}
